/**
 * ============用户认证控制器开始===========
 * 用户认证控制器 - 提供用户注册、登录、验证码发送等功能
 * User Authentication Controller - Provides user registration, login, verification code sending functions
 * 
 * 功能说明：
 * - 支持手机号和邮箱两种注册登录方式
 * - 提供短信和邮箱验证码发送功能
 * - 实现用户密码加密存储和JWT令牌生成
 * - 包含完整的参数验证和错误处理机制
 * 
 * 依赖模块说明：
 * - bcryptjs: 用于密码加密，使用 bcrypt.hash() 加密，bcrypt.compare() 验证
 * - UserModel: 用户数据模型，提供用户CRUD操作
 * - VerificationModel: 验证码数据模型，管理验证码生命周期
 * - generateToken: JWT令牌生成工具，用于用户身份认证
 * - logger: 日志记录工具，记录操作日志和错误信息
 */

// 导入必要的依赖包和模块 - Import necessary dependencies and modules
import bcrypt from "bcryptjs";                              // 密码加密库 - Password encryption library
import { UserModel } from "../models/userModel.js";         // 用户数据模型 - User data model
import { VerificationModel } from "../models/verificationModel.js"; // 验证码数据模型 - Verification code data model
import { generateToken } from "../utils/token.js";          // JWT 令牌生成工具 - JWT token generation utility
import { logger } from "../utils/logger.js";                // 日志记录工具 - Logging utility

/**
 * ============发送短信验证码功能开始===========
 * 发送短信验证码
 * Send SMS verification code
 * 
 * @param {Object} req - Express请求对象，包含用户提交的数据
 * @param {Object} res - Express响应对象，用于返回结果给客户端
 * @param {Function} next - Express中间件函数，用于错误处理
 * @returns {Promise<void>} 无返回值，通过res对象返回JSON响应
 * @throws {Error} 当手机号格式错误、验证码生成失败或数据库操作失败时抛出异常
 * 
 * 功能说明：
 * - 向用户手机发送6位数字验证码，用于注册或登录验证
 * - 验证码有效期为5分钟，过期后需重新获取
 * - 支持中国大陆手机号格式验证（1开头，第二位3-9，总共11位）
 * - 开发环境下会在响应中返回验证码，生产环境不返回
 * 
 * 请求参数：
 * - phone: 手机号码，必须符合中国大陆手机号格式
 * 
 * 响应格式：
 * {
 *   success: boolean,     // 操作是否成功
 *   message: string,      // 提示信息
 *   data: {
 *     phone: string,      // 手机号
 *     code?: string       // 验证码（仅开发环境）
 *   }
 * }
 * 
 * 使用示例：
 * POST /api/auth/request-sms-code
 * Body: { "phone": "13800138000" }
 * 
 * 异常处理：
 * - 400: 手机号格式错误
 * - 500: 服务器内部错误（验证码生成或存储失败）
 */
export const requestSmsCode = async (req, res, next) => {
  try {
    // 第一步：从请求体中获取手机号 - Step 1: Get phone number from request body
    const { phone } = req.body;

    // 第二步：验证手机号格式 - Step 2: Validate phone number format
    // 中国手机号正则：1开头，第二位是3-9，总共11位数字 - Chinese phone regex: starts with 1, second digit 3-9, total 11 digits
    if (!phone || !/^1[3-9]\d{9}$/.test(phone)) {
      return res.status(400).json({
        success: false,
        message: "请输入有效的手机号",
        data: null,
      });
    }

    // 第三步：生成6位随机验证码 - Step 3: Generate 6-digit random verification code
    // Math.random() 生成0-1之间的随机数，乘以900000得到0-899999，加上100000得到100000-999999
    const code = Math.floor(100000 + Math.random() * 900000).toString();

    // 第四步：将验证码存储到数据库 - Step 4: Store verification code in database
    // VerificationModel.createCode() 方法会自动设置过期时间和状态
    await VerificationModel.createCode({
      target: phone,              // 目标手机号 - Target phone number
      code,                       // 验证码 - Verification code
      type: "sms",               // 验证码类型：短信 - Code type: SMS
      expiresInMinutes: 5,       // 过期时间：5分钟 - Expiration time: 5 minutes
    });

    // 第五步：记录日志和控制台输出 - Step 5: Log and console output
    // TODO: 在实际项目中，这里应该调用真实的短信服务API（如阿里云、腾讯云等）
    // TODO: In real projects, this should call actual SMS service API (like Aliyun, Tencent Cloud, etc.)
    logger.info(`[SMS] 发送验证码 ${code} 到手机 ${phone}`);
    console.log(`📱 短信验证码已发送到 ${phone}: ${code}`);

    // 第六步：返回成功响应 - Step 6: Return success response
    res.json({
      success: true,
      message: "验证码已发送",
      data: {
        phone,
        // 开发环境返回验证码方便测试，生产环境应删除此行 - Return code in dev environment for testing, remove in production
        ...(process.env.NODE_ENV === "development" && { code }),
      },
    });
  } catch (error) {
    // 第七步：错误处理 - Step 7: Error handling
    logger.error("发送短信验证码失败:", error);
    res.status(500).json({
      success: false,
      message: "发送验证码失败，请稍后重试",
      data: null,
    });
  }
};

/**
 * ============发送邮箱验证码功能开始===========
 * 发送邮箱验证码
 * Send email verification code
 * 
 * @param {Object} req - Express请求对象
 * @param {Object} res - Express响应对象
 * @param {Function} next - Express中间件函数
 * @returns {Promise<void>} 无返回值，通过res对象返回JSON响应
 * @throws {Error} 当邮箱格式错误、验证码生成失败或数据库操作失败时抛出异常
 * 
 * 功能说明：
 * - 向用户邮箱发送6位数字验证码，用于注册或登录验证
 * - 验证码有效期为10分钟，比短信验证码稍长
 * - 支持标准邮箱格式验证（包含@符号和域名）
 * - 开发环境下会在响应中返回验证码，生产环境不返回
 * 
 * 请求参数：
 * - email: 邮箱地址，必须符合标准邮箱格式
 * 
 * 响应格式：
 * {
 *   success: boolean,     // 操作是否成功
 *   message: string,      // 提示信息
 *   data: {
 *     email: string,      // 邮箱地址
 *     code?: string       // 验证码（仅开发环境）
 *   }
 * }
 * 
 * 使用示例：
 * POST /api/auth/request-email-code
 * Body: { "email": "user@example.com" }
 * 
 * 异常处理：
 * - 400: 邮箱格式错误
 * - 500: 服务器内部错误（验证码生成或存储失败）
 */
export const requestEmailCode = async (req, res, next) => {
  try {
    // 第一步：从请求体中获取邮箱地址 - Step 1: Get email address from request body
    const { email } = req.body;

    // 第二步：验证邮箱格式 - Step 2: Validate email format
    // 标准邮箱正则：包含@符号，@前后都有字符，最后有域名后缀 - Standard email regex
    if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
      return res.status(400).json({
        success: false,
        message: "请输入有效的邮箱地址",
        data: null,
      });
    }

    // 第三步：生成6位随机验证码 - Step 3: Generate 6-digit random verification code
    const code = Math.floor(100000 + Math.random() * 900000).toString();

    // 第四步：将验证码存储到数据库 - Step 4: Store verification code in database
    await VerificationModel.createCode({
      target: email,              // 目标邮箱 - Target email
      code,                       // 验证码 - Verification code
      type: "email",             // 验证码类型：邮箱 - Code type: Email
      expiresInMinutes: 10,      // 过期时间：10分钟 - Expiration time: 10 minutes
    });

    // 第五步：记录日志和控制台输出 - Step 5: Log and console output
    // TODO: 在实际项目中，这里应该调用真实的邮件服务API（如SendGrid、阿里云邮件推送等）
    // TODO: In real projects, this should call actual email service API (like SendGrid, Aliyun Email Push, etc.)
    logger.info(`[EMAIL] 发送验证码 ${code} 到邮箱 ${email}`);
    console.log(`📧 邮箱验证码已发送到 ${email}: ${code}`);

    // 第六步：返回成功响应 - Step 6: Return success response
    res.json({
      success: true,
      message: "验证码已发送",
      data: {
        email,
        // 开发环境返回验证码，生产环境删除此行 - Return code in dev environment, remove in production
        ...(process.env.NODE_ENV === "development" && { code }),
      },
    });
  } catch (error) {
    // 第七步：错误处理 - Step 7: Error handling
    logger.error("发送邮箱验证码失败:", error);
    res.status(500).json({
      success: false,
      message: "发送验证码失败，请稍后重试",
      data: null,
    });
  }
};

/**
 * ============用户注册功能开始===========
 * 用户注册
 * User registration
 * 
 * @param {Object} req - Express请求对象
 * @param {Object} res - Express响应对象
 * @param {Function} next - Express中间件函数
 * @returns {Promise<void>} 无返回值，通过res对象返回JSON响应
 * @throws {Error} 当参数验证失败、用户已存在或数据库操作失败时抛出异常
 * 
 * 功能说明：
 * - 支持手机号和邮箱两种注册方式
 * - 验证码验证通过后创建新用户账户
 * - 密码使用bcrypt加密存储，安全性高
 * - 注册成功后自动生成JWT令牌用于身份认证
 * - 防止重复注册，已存在账户返回409状态码
 * 
 * 请求参数：
 * - password: 密码，至少6位字符
 * - phone?: 手机号（手机注册时必填）
 * - smsCode?: 短信验证码（手机注册时必填）
 * - email?: 邮箱地址（邮箱注册时必填）
 * - emailCode?: 邮箱验证码（邮箱注册时必填）
 * 
 * 响应格式：
 * {
 *   success: boolean,
 *   message: string,
 *   data: {
 *     user: {
 *       id: number,
 *       phone?: string,
 *       email?: string,
 *       loginProvider: string
 *     },
 *     token: string
 *   }
 * }
 * 
 * 使用示例：
 * POST /api/auth/register
 * Body: { 
 *   "phone": "13800138000", 
 *   "smsCode": "123456", 
 *   "password": "password123" 
 * }
 * 
 * 异常处理：
 * - 400: 参数验证失败（密码长度不足、验证码无效等）
 * - 409: 账户已存在
 * - 500: 服务器内部错误
 */
export const register = async (req, res, next) => {
  try {
    // 第一步：获取请求参数 - Step 1: Get request parameters
    const { phone, email, password, smsCode, emailCode } = req.body;

    // 第二步：验证密码格式 - Step 2: Validate password format
    if (!password || password.length < 6) {
      return res.status(400).json({
        success: false,
        message: "密码至少需要6位",
        data: null,
      });
    }

    let newUser;
    let loginProvider;

    // 第三步：处理手机号注册流程 - Step 3: Handle phone registration process
    if (phone && smsCode) {
      // 验证手机号格式 - Validate phone format
      if (!/^1[3-9]\d{9}$/.test(phone)) {
        return res.status(400).json({
          success: false,
          message: "手机号格式不正确",
          data: null,
        });
      }

      // 检查手机号是否已注册 - Check if phone already registered
      // UserModel.findByPhone() 方法查询数据库中是否存在该手机号
      const existingUser = await UserModel.findByPhone(phone);
      if (existingUser) {
        return res.status(409).json({
          success: false,
          message: "该手机号已注册，请直接登录",
          data: {
            accountType: "phone",
            account: phone,
            existingAccount: true,
          },
        });
      }

      // 验证短信验证码 - Verify SMS code
      // VerificationModel.verifyCode() 方法验证验证码是否有效且未过期
      const verificationRecord = await VerificationModel.verifyCode({
        target: phone,
        code: smsCode,
        type: "sms",
      });

      if (!verificationRecord) {
        return res.status(400).json({
          success: false,
          message: "验证码无效或已过期",
          data: null,
        });
      }

      // 创建用户 - Create user
      loginProvider = "phone";
      newUser = await UserModel.create({
        phone,
        password,
        loginProvider,
      });

      // 标记验证码已使用 - Mark verification code as used
      await VerificationModel.markUsed(verificationRecord.id);

    // 第四步：处理邮箱注册流程 - Step 4: Handle email registration process
    } else if (email && emailCode) {
      // 验证邮箱格式 - Validate email format
      if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
        return res.status(400).json({
          success: false,
          message: "邮箱格式不正确",
          data: null,
        });
      }

      // 检查邮箱是否已注册 - Check if email already registered
      const existingUser = await UserModel.findByEmail(email);
      if (existingUser) {
        return res.status(409).json({
          success: false,
          message: "该邮箱已注册，请直接登录",
          data: {
            accountType: "email",
            account: email,
            existingAccount: true,
          },
        });
      }

      // 验证邮箱验证码 - Verify email code
      const verificationRecord = await VerificationModel.verifyCode({
        target: email,
        code: emailCode,
        type: "email",
      });

      if (!verificationRecord) {
        return res.status(400).json({
          success: false,
          message: "验证码无效或已过期",
          data: null,
        });
      }

      // 创建用户 - Create user
      loginProvider = "email";
      newUser = await UserModel.create({
        email,
        password,
        loginProvider,
      });

      // 标记验证码已使用 - Mark verification code as used
      await VerificationModel.markUsed(verificationRecord.id);

    } else {
      // 第五步：参数不完整处理 - Step 5: Handle incomplete parameters
      return res.status(400).json({
        success: false,
        message: "请提供完整的注册信息（手机号+短信验证码 或 邮箱+邮箱验证码）",
        data: null,
      });
    }

    // 第六步：生成JWT令牌 - Step 6: Generate JWT token
    // generateToken() 方法基于用户ID和登录方式生成JWT令牌
    const token = generateToken({
      userId: newUser.id,
      loginProvider,
    });

    // 第七步：记录日志 - Step 7: Log the registration
    logger.info(`用户注册成功: ${loginProvider === "phone" ? phone : email}`);

    // 第八步：返回成功响应 - Step 8: Return success response
    res.status(201).json({
      success: true,
      message: "注册成功",
      data: {
        user: {
          id: newUser.id,
          ...(phone && { phone }),
          ...(email && { email }),
          loginProvider,
        },
        token,
      },
    });

  } catch (error) {
    // 第九步：错误处理 - Step 9: Error handling
    logger.error("用户注册失败:", error);
    res.status(500).json({
      success: false,
      message: "注册失败，请稍后重试",
      data: null,
    });
  }
};

/**
 * ============用户登录功能开始===========
 * 用户登录
 * User login
 * 
 * @param {Object} req - Express请求对象
 * @param {Object} res - Express响应对象
 * @param {Function} next - Express中间件函数
 * @returns {Promise<void>} 无返回值，通过res对象返回JSON响应
 * @throws {Error} 当参数验证失败、用户不存在或密码错误时抛出异常
 * 
 * 功能说明：
 * - 支持手机号和邮箱两种登录方式
 * - 使用bcrypt验证密码，确保安全性
 * - 登录成功后生成JWT令牌用于后续身份认证
 * - 返回用户基本信息（不包含敏感数据如密码）
 * 
 * 请求参数：
 * - account: 账户（手机号或邮箱）
 * - password: 密码
 * - loginType: 登录类型（"phone" 或 "email"）
 * 
 * 响应格式：
 * {
 *   success: boolean,
 *   message: string,
 *   data: {
 *     user: {
 *       id: number,
 *       phone?: string,
 *       email?: string,
 *       loginProvider: string
 *     },
 *     token: string
 *   }
 * }
 * 
 * 使用示例：
 * POST /api/auth/login
 * Body: { 
 *   "account": "13800138000", 
 *   "password": "password123", 
 *   "loginType": "phone" 
 * }
 * 
 * 异常处理：
 * - 400: 参数验证失败
 * - 404: 账户不存在
 * - 401: 密码错误
 * - 500: 服务器内部错误
 */
export const login = async (req, res, next) => {
  try {
    // 第一步：获取请求参数 - Step 1: Get request parameters
    const { account, password, loginType } = req.body;

    // 第二步：参数验证 - Step 2: Parameter validation
    if (!account || !password || !loginType) {
      return res.status(400).json({
        success: false,
        message: "请提供完整的登录信息",
        data: null,
      });
    }

    if (!["phone", "email"].includes(loginType)) {
      return res.status(400).json({
        success: false,
        message: "登录类型无效",
        data: null,
      });
    }

    // 第三步：根据登录类型查找用户 - Step 3: Find user by login type
    let user;
    if (loginType === "phone") {
      // 验证手机号格式 - Validate phone format
      if (!/^1[3-9]\d{9}$/.test(account)) {
        return res.status(400).json({
          success: false,
          message: "手机号格式不正确",
          data: null,
        });
      }
      // UserModel.findByPhone() 方法根据手机号查找用户
      user = await UserModel.findByPhone(account);
    } else {
      // 验证邮箱格式 - Validate email format
      if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(account)) {
        return res.status(400).json({
          success: false,
          message: "邮箱格式不正确",
          data: null,
        });
      }
      // UserModel.findByEmail() 方法根据邮箱查找用户
      user = await UserModel.findByEmail(account);
    }

    // 第四步：检查用户是否存在 - Step 4: Check if user exists
    if (!user) {
      return res.status(404).json({
        success: false,
        message: "账号不存在，请先注册",
        data: {
          accountType: loginType,
          account,
          needRegister: true,
        },
      });
    }

    // 第五步：验证密码 - Step 5: Verify password
    // bcrypt.compare() 方法比较明文密码和加密后的密码哈希
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
      return res.status(401).json({
        success: false,
        message: "密码错误",
        data: null,
      });
    }

    // 第六步：生成JWT令牌 - Step 6: Generate JWT token
    const token = generateToken({
      userId: user.id,
      loginProvider: user.loginProvider,
    });

    // 第七步：记录登录日志 - Step 7: Log the login
    logger.info(`用户登录成功: ${account} (${loginType})`);

    // 第八步：返回成功响应 - Step 8: Return success response
    res.json({
      success: true,
      message: "登录成功",
      data: {
        user: {
          id: user.id,
          phone: user.phone,
          email: user.email,
          loginProvider: user.loginProvider,
        },
        token,
      },
    });

  } catch (error) {
    // 第九步：错误处理 - Step 9: Error handling
    logger.error("用户登录失败:", error);
    res.status(500).json({
      success: false,
      message: "登录失败，请稍后重试",
      data: null,
    });
  }
};

/**
 * 获取用户信息
 */
export const getUserInfo = async (req, res, next) => {
  try {
    const userId = req.user.id;
    const user = await UserModel.findById(userId);
    
    if (!user) {
      return res.status(404).json({
        success: false,
        message: "用户不存在",
        data: null,
      });
    }

    res.json({
      success: true,
      message: "获取用户信息成功",
      data: {
        id: user.id,
        phone: user.phone || null,
        email: user.email || null,
        nickname: user.nickname || null,
        avatar: user.avatar || null,
        birthDate: user.birthDate || null,
        birthTime: user.birthTime || null,
        gender: user.gender || null,
        location: user.location || null,
        createdAt: user.createdAt,
        updatedAt: user.updatedAt,
      },
    });
  } catch (error) {
    logger.error("获取用户信息失败:", error);
    res.status(500).json({
      success: false,
      message: "获取用户信息失败",
      data: null,
    });
  }
};

/**
 * 更新用户信息
 */
export const updateUserInfo = async (req, res, next) => {
  try {
    const userId = req.user.id;
    const { nickname, avatar, birthDate, birthTime, gender, location } = req.body;

    // 验证出生日期格式
    if (birthDate && !/^\d{4}-\d{2}-\d{2}$/.test(birthDate)) {
      return res.status(400).json({
        success: false,
        message: "出生日期格式错误，请使用YYYY-MM-DD格式",
        data: null,
      });
    }

    // 验证出生时间格式
    if (birthTime && !/^\d{2}:\d{2}$/.test(birthTime)) {
      return res.status(400).json({
        success: false,
        message: "出生时间格式错误，请使用HH:MM格式",
        data: null,
      });
    }

    // 验证性别
    if (gender && !['male', 'female'].includes(gender)) {
      return res.status(400).json({
        success: false,
        message: "性别参数无效，请使用male或female",
        data: null,
      });
    }

    const updateData = {};
    if (nickname !== undefined) updateData.nickname = nickname;
    if (avatar !== undefined) updateData.avatar = avatar;
    if (birthDate !== undefined) updateData.birthDate = birthDate;
    if (birthTime !== undefined) updateData.birthTime = birthTime;
    if (gender !== undefined) updateData.gender = gender;
    if (location !== undefined) updateData.location = location;

    const updatedUser = await UserModel.updateById(userId, updateData);

    if (!updatedUser) {
      return res.status(404).json({
        success: false,
        message: "用户不存在",
        data: null,
      });
    }

    logger.info(`用户信息更新成功：${userId}`);

    res.json({
      success: true,
      message: "用户信息更新成功",
      data: {
        id: updatedUser.id,
        phone: updatedUser.phone || null,
        email: updatedUser.email || null,
        nickname: updatedUser.nickname || null,
        avatar: updatedUser.avatar || null,
        birthDate: updatedUser.birthDate || null,
        birthTime: updatedUser.birthTime || null,
        gender: updatedUser.gender || null,
        location: updatedUser.location || null,
        updatedAt: updatedUser.updatedAt,
      },
    });
  } catch (error) {
    logger.error("更新用户信息失败:", error);
    res.status(500).json({
      success: false,
      message: "更新用户信息失败",
      data: null,
    });
  }
};

/**
 * 修改密码
 */
export const changePassword = async (req, res, next) => {
  try {
    const userId = req.user.id;
    const { oldPassword, newPassword } = req.body;

    if (!oldPassword || !newPassword) {
      return res.status(400).json({
        success: false,
        message: "请提供旧密码和新密码",
        data: null,
      });
    }

    if (newPassword.length < 6) {
      return res.status(400).json({
        success: false,
        message: "新密码至少需要6位",
        data: null,
      });
    }

    const user = await UserModel.findById(userId);
    if (!user) {
      return res.status(404).json({
        success: false,
        message: "用户不存在",
        data: null,
      });
    }

    // 验证旧密码
    const isValidPassword = await bcrypt.compare(oldPassword, user.passwordHash);
    if (!isValidPassword) {
      return res.status(401).json({
        success: false,
        message: "旧密码错误",
        data: null,
      });
    }

    // 更新密码
    await UserModel.updateById(userId, { password: newPassword });

    logger.info(`用户修改密码成功：${userId}`);

    res.json({
      success: true,
      message: "密码修改成功",
      data: null,
    });
  } catch (error) {
    logger.error("修改密码失败:", error);
    res.status(500).json({
      success: false,
      message: "修改密码失败",
      data: null,
    });
  }
};

/**
 * 微信登录（暂未实现）
 */
export const loginWithWeChat = async (req, res, next) => {
  try {
    logger.info("微信登录请求");
    res.status(501).json({
      success: false,
      message: "微信登录功能正在开发中，敬请期待",
      data: null,
    });
  } catch (error) {
    next(error);
  }
};
